package com.hexus.eve.utils;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.hexus.eve.entities.Translatable;
import javax.annotation.PostConstruct;


@SuppressWarnings("restriction")
@Service
public class TranslationUtils {
	private static final String[] DEFAULT_SUPPORTED_LANGUAGES = new String[]{"RU"};
	private Map<String, Map<String, Map<Integer, Map<String, String>>>> translations = new HashMap<String, Map<String, Map<Integer, Map<String,String>>>>();
	
	private static volatile TranslationUtils instance;
	
	@Autowired
	private SessionFactory sessionFactory;

	private TranslationUtils(){};
	
	@SuppressWarnings("unused")
	@PostConstruct
	private void init(){
		String[] languages = DEFAULT_SUPPORTED_LANGUAGES;
		
		ResourceBundle bundle = ResourceBundle.getBundle("global");
		String supportedLanguages = bundle.getString("supported.languages");
		if(supportedLanguages != null && !"".equals(supportedLanguages)){
			languages = supportedLanguages.split(",");
		}
		 
		for(int i = 0; i < languages.length; i++)
			populateTranslations(languages[i]);
		
		instance = this;	  
	}	
	
	private void populateTranslations(String language){
		if(!translations.containsKey(language)) {
			Map<String, Map<Integer, Map<String, String>>> t = new HashMap<String, Map<Integer, Map<String, String>>>();
			translations.put(language, t);
		}
		Map<String, Map<Integer, Map<String, String>>> languageTranslations = (Map<String, Map<Integer, Map<String, String>>>) translations.get(language);
		
		Session session = sessionFactory.openSession();
		@SuppressWarnings("unchecked")
		List<Object[]> results = session.createSQLQuery("SELECT tableName, columnName, text, keyID FROM Translations where languageID=:language")
		.addScalar("tableName", Hibernate.STRING)
		.addScalar("columnName", Hibernate.STRING)
		.addScalar("text", Hibernate.STRING)
		.addScalar("keyID", Hibernate.INTEGER)
		.setString("language", language)		
		.list();
		
		for (Object[] item: results) {
			String table = (String) item[0];
			String column = (String) item[1];
			String text = (String) item[2];
			Integer record = (Integer) item[3];
			
			if(!languageTranslations.containsKey(table)) {
				languageTranslations.put(table, new HashMap<Integer, Map<String,String>>());
			}
			Map<Integer, Map<String, String>> tableTranslations = languageTranslations.get(table);
			
			if(!tableTranslations.containsKey(record)) {
				tableTranslations.put(record, new HashMap<String, String>());
			}
			
			Map<String, String> recordTranslations = tableTranslations.get(record);			
						
			if(!recordTranslations.containsKey(column)){
				recordTranslations.put(column, text);
			}			
		}	
		session.close();
	} 
	
	public Map<String, String> getRecordTranslations(String language, String tableName, Integer recordId) {
		Map<String, String> results = EmptyItems.HASHMAP_STRING_STRING;
		if(translations.containsKey(language)) {
			Map<String, Map<Integer, Map<String, String>>> languageTranslations = translations.get(language);
			if(languageTranslations.containsKey(tableName)){
				Map<Integer, Map<String, String>> tableTranslations = languageTranslations.get(tableName);
				if(tableTranslations.containsKey(recordId)) {
					results = tableTranslations.get(recordId);
				}
			}
		}
		return results;
	}
	
	public Map<String, String> getRecordTranslations(Locale locale, String tableName, Integer recordId) {
		return getRecordTranslations(locale.getLanguage().toUpperCase(), tableName, recordId);
	}
	
	
	public static TranslationUtils getInstance(){
		if (instance == null) {
			synchronized (TranslationUtils.class) {
				instance = new TranslationUtils();	
			}
		} 
		return instance;
	}
	
	
	public Object translate(Object obj, Locale locale) {
		if(obj instanceof Translatable) {
			Translatable t = (Translatable) obj; 
			t.translate(getRecordTranslations(locale, t.getTableName(),  t.getId()), locale);
		}
		return obj;
	}
	
	@SuppressWarnings("rawtypes")
	public Object translate(List list, Locale locale) {
		for(int i = 0; i < list.size(); i++) {
			translate(list.get(i), locale);
		}
		return list;
	}
}
